package com.g0dkar.leet.util.ognl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import ognl.DynamicSubscript;
import ognl.ListPropertyAccessor;
import ognl.OgnlException;

/**
 * <p>
 * This class does the same as OGNL's {@link ListPropertyAccessor}, but for {@link Set Sets}.
 * </p>
 * <h4>Attention</h4>
 * <p>
 * The most commonly used {@link Set} in Java is {@link HashMap}, which does <strong>not</strong> maintain the order of
 * the elements within it. Because of this characteristic, indexed access may not be in the same order as expected. If
 * you need ordered indexed access to a Set elements in the same way as a List, please use a {@link LinkedHashSet} or
 * {@link TreeSet}. A {@link LinkedHashSet} have a slighly slower performance than the {@link HashSet}, but it keeps the
 * order of the elements within it.
 * </p>
 * 
 * @author Rafael g0dkar Lins
 * 
 */
public class LeetOGNLSetPropertyAccessor extends ListPropertyAccessor {
	public Object getProperty(Map context, Object target, Object name) throws OgnlException {
		System.out.println("[JHeatOGNLSetPropertyAccessor] context = " + context + ", target = " + target + ", oname = " + name);
		Set set = (Set) target;
		return super.getProperty(context, new ArrayList(set), name);
	}
	
	public void setProperty(Map context, Object target, Object name, Object value) throws OgnlException {
		if (name instanceof Number) {
			Set set = (Set) target;
			set.add(value);
		}
		else if (name instanceof DynamicSubscript) {
			Set set = (Set) target;
			switch (((DynamicSubscript) name).getFlag()) {
				case DynamicSubscript.FIRST:
				case DynamicSubscript.MID:
				case DynamicSubscript.LAST: {
					set.add(value);
					return;
				}
				case DynamicSubscript.ALL: {
					if (!(value instanceof Collection)) {
						throw new OgnlException("Value must be a collection");
					}
					
					set.clear();
					set.addAll((Collection) value);
					return;
				}
			}
		}
		else {
			super.setProperty(context, target, name, value);
		}
	}
}
